package com.xinqi.modules.sys.textbook.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.google.common.collect.ImmutableList;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.base.response.PageInfo;
import com.xinqi.common.base.response.Param;
import com.xinqi.common.base.utils.json.JSON;
import com.xinqi.common.mybatis.utils.Pages;
import com.xinqi.common.mybatis.utils.Queries;
import com.xinqi.modules.sys.textbook.convert.CloudTextbookInfoConvert;
import com.xinqi.modules.sys.textbook.domain.CloudTextbookInfoEntity;
import com.xinqi.modules.sys.textbook.dto.req.CloudTextbookInfoCreateDTO;
import com.xinqi.modules.sys.textbook.dto.req.CloudTextbookInfoDeleteDTO;
import com.xinqi.modules.sys.textbook.dto.req.CloudTextbookInfoQueryDTO;
import com.xinqi.modules.sys.textbook.dto.req.CloudTextbookInfoUpdateDTO;
import com.xinqi.modules.sys.textbook.dto.rsp.CloudTextbookInfoResultDTO;
import com.xinqi.modules.sys.textbook.enums.TextbookStatusEnum;
import com.xinqi.modules.sys.textbook.manager.CloudTextbookInfoManager;
import com.xinqi.modules.sys.textbook.service.CloudTextbookInfoService;
import com.xinqi.modules.sys.util.IKSegmenterUtil;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 云课本基本信息服务层实现
 *
 * @author: linkai
 * @date: 2023/04/25
 */
@Slf4j
@Validated
@Service("cloudTextbookInfoService")
@RequiredArgsConstructor
public class CloudTextbookInfoServiceImpl implements CloudTextbookInfoService {
    private final CloudTextbookInfoConvert cloudTextbookInfoConvert;
    private final CloudTextbookInfoManager cloudTextbookInfoManager;

    /**
     * 分页查询 云课本基本信息数据
     */
    @Override
    @DS("slaver")
    public PageInfo<CloudTextbookInfoResultDTO> page(Param pageable, CloudTextbookInfoQueryDTO query) {
        //排序
        if (CollectionUtils.isEmpty(pageable.getSorts())) {
            pageable.setSorts(new ArrayList<>());
        }
        pageable.getSorts().add("a.sort,DESC");
        if (Objects.nonNull(query.getName())) {
            query.setNames(IKSegmenterUtil.singleSplice(query.getName()));
        }
        IPage<CloudTextbookInfoResultDTO> page = cloudTextbookInfoManager.findPage(Pages.page(pageable), query);
        return Pages.convert(page);
    }

    /**
     * 查询 云课本基本信息数据
     */
    @DS("slaver")
    @Override
    public List<CloudTextbookInfoResultDTO> find(CloudTextbookInfoQueryDTO query) {
        return cloudTextbookInfoManager.list(wrapper(query)).stream()
            .map(cloudTextbookInfoConvert::convert).collect(Collectors.toList());
    }

    private LambdaQueryWrapper<CloudTextbookInfoEntity> wrapper(CloudTextbookInfoQueryDTO query) {
        LambdaQueryWrapper<CloudTextbookInfoEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(CloudTextbookInfoEntity::getId, v));
        if (Objects.nonNull(query.getName())) {
            List<String> names = IKSegmenterUtil.singleSplice(query.getName());
            if (CollectionUtils.isNotEmpty(names)) {
                for (String name : names) {
                    Queries.accept(name, v -> wrapper.like(CloudTextbookInfoEntity::getName, v));
                }
            }
        }
        Queries.accept(query.getVersionId(), v -> wrapper.eq(CloudTextbookInfoEntity::getVersionId, v));
        Queries.accept(query.getStageId(), v -> wrapper.eq(CloudTextbookInfoEntity::getStageId, v));
        Queries.accept(query.getSubjectId(), v -> wrapper.eq(CloudTextbookInfoEntity::getSubjectId, v));
        Queries.accept(query.getStatus(), v -> wrapper.eq(CloudTextbookInfoEntity::getStatus, v.getCode()));
        wrapper.orderByAsc(CloudTextbookInfoEntity::getSort);
        return wrapper;
    }

    /**
     * 根据id查询 云课本基本信息数据
     */
    @DS("slaver")
    @Override
    public CloudTextbookInfoResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return Optional.ofNullable(cloudTextbookInfoManager.findById(id)).map(cloudTextbookInfoConvert::convert).orElse(null);
    }

    @Override
    public Boolean isExistName(String name, Long oId) {
        return cloudTextbookInfoManager.isExistName(name, oId);
    }

    /**
     * 新增 云课本基本信息数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(@Valid CloudTextbookInfoCreateDTO dto) {
        CloudTextbookInfoEntity entity = cloudTextbookInfoConvert.create(dto);
        CommonErrors.BAD_REQUEST.check(!isExistName(entity.getName(), null), "名称已存在");
        entity.setStatus(TextbookStatusEnum.ENABLE);
        cloudTextbookInfoManager.save(entity);
        return entity.getId();
    }

    /**
     * 根据id修改 云课本基本信息数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(@Valid CloudTextbookInfoUpdateDTO dto) {
        Optional.ofNullable(cloudTextbookInfoManager.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException("数据不存在"));
        CommonErrors.BAD_REQUEST.check(!isExistName(dto.getName(), dto.getId()), "名称已存在");
        CloudTextbookInfoEntity entity = cloudTextbookInfoConvert.update(dto);
        return cloudTextbookInfoManager.updateById(entity);
    }

    /**
     * 根据id删除 云课本基本信息数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), "ID不能为空");
        return cloudTextbookInfoManager.removeById(id);
    }

    /**
     * 根据id删除 云课本基本信息数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(CloudTextbookInfoDeleteDTO dto) {
        return deleteById(dto.getId());
    }

    /**
     * 导入课本信息
     *
     * @param file 文件
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<String> upload(MultipartFile file) {
        log.info("课本导入，文件名为：{}，大小： {}", file.getOriginalFilename(), file.getSize());
        ImmutableList.Builder<String> builder = new ImmutableList.Builder<>();
        try {
            EasyExcel.read(file.getInputStream(), TextBookImport.class, new PageReadListener<TextBookImport>(dataList -> {
                ImmutableList.Builder<CloudTextbookInfoEntity> updateList = new ImmutableList.Builder<>();
                for (TextBookImport demoData : dataList) {
                    // 保存信息
                    CloudTextbookInfoEntity entity = cloudTextbookInfoManager.findByName(demoData.getName());
                    if (entity != null) {
                        entity.setPublisher(demoData.getPublisher());
                        entity.setIsbn(demoData.getIsbn());
                        updateList.add(entity);
                    } else {
                        builder.add(StrUtil.format("云课本未找到，课本名为: {}", demoData.getName()));
                    }
                }
                cloudTextbookInfoManager.updateBatchById(updateList.build());
            })).sheet().headRowNumber(1).doRead();
        } catch (IOException e) {
            throw CommonErrors.BAD_REQUEST.asException("导入课本信息失败，文件名：{}", file.getOriginalFilename());
        }
        return builder.build();
    }

    @Accessors(chain = false)
    @Data
    public static class TextBookImport {
        /**
         * 名称
         */
        @ExcelProperty(index = 0)
        private String name;
        /**
         * 出版社
         */
        @ExcelProperty(index = 1)
        private String publisher;
        /**
         * ISBN
         */
        @ExcelProperty(index = 2)
        private String isbn;
    }
}
